/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.pc9.pswing.components.filebrowser;

import br.com.pc9.pswing.components.SearchComponent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.AbstractButton;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;

/**
 *
 * @author paulocanedo
 */
public class PFileBrowser {

    private boolean canceled = false;
    private JDialog fileBrowserDialog;
    private PFileBrowserView fileBrowserPanel = new PFileBrowserView();
    private FileBrowserModelFactory modelFactory;
    private FileBrowserListenerFactory listenerFactory;
    private List<FileFilter> fileFilters = new ArrayList<FileFilter>();
    private int width = 660;
    private int height = 490;

    public PFileBrowser() {
        init();
    }

    private void init() {
        modelFactory = new FileBrowserModelFactory();
        listenerFactory = new FileBrowserListenerFactory(modelFactory);

        AbstractButton backButton = fileBrowserPanel.getButton(PFileBrowserView.BACK_BUTTON);
        backButton.addActionListener(listenerFactory.createBackListener());
        AbstractButton forwardButton = fileBrowserPanel.getButton(PFileBrowserView.FORWARD_BUTTON);
        forwardButton.addActionListener(listenerFactory.createForwardListener());
        AbstractButton gotoButton = fileBrowserPanel.getButton(PFileBrowserView.GOTO_BUTTON);
        gotoButton.addActionListener(listenerFactory.createGotoListener());

        fileBrowserPanel.getComponent(PFileBrowserView.PREVIEW_BUTTON);
        fileBrowserPanel.getComponent(PFileBrowserView.SHOW_HIDDEN_BUTTON);

        JList favoriteList = fileBrowserPanel.getJList(PFileBrowserView.FAVORITE_LIST);
        favoriteList.setModel(modelFactory.getFavoritePlacesListModel());
        favoriteList.addListSelectionListener(listenerFactory.createFavoriteNavigationListSelectionListener(favoriteList));
        favoriteList.addMouseListener(listenerFactory.createHotfileMouseListener(favoriteList));

        JComboBox navigationComboBox = (JComboBox) fileBrowserPanel.getComponent(PFileBrowserView.NAVIGATION_FOLDERS_COMBOBOX);
        navigationComboBox.setModel(modelFactory.getNavigationComboBoxModel());
        navigationComboBox.addItemListener(listenerFactory.createNavigationItemListener(navigationComboBox));

        final SearchComponent searchComponent = (SearchComponent) fileBrowserPanel.getComponent(PFileBrowserView.SEARCH_COMPONENT);
        searchComponent.addSearchTextChangedListener(new SearchComponent.SearchTextChangedListener() {

            @Override
            public void textChanged(String newText) {
                modelFactory.getBrowserListModel().setPrefixFilter(newText);
            }
        });

        JList browserList = fileBrowserPanel.getJList(PFileBrowserView.BROWSER_LIST);
        browserList.setModel(modelFactory.getBrowserListModel());
        browserList.addMouseListener(listenerFactory.createBrowserMouseListener(browserList));
        browserList.setCellRenderer(new FileFilterCellRenderer(browserList.getCellRenderer()));

        AbstractButton newFolderButton = (AbstractButton) fileBrowserPanel.getComponent(PFileBrowserView.NEW_FOLDER_BUTTON);
        newFolderButton.addActionListener(listenerFactory.createNewFolderAction(fileBrowserDialog));

        AbstractButton cancelButton = fileBrowserPanel.getButton(PFileBrowserView.CANCEL_BUTTON);
        cancelButton.addActionListener(new CancelActionListener());

        AbstractButton confirmButton = fileBrowserPanel.getButton(PFileBrowserView.CONFIRM_BUTTON);
        confirmButton.addActionListener(new ConfirmActionListener());
    }

    public void setStrings(String confirmButtonText, String cancelButtonText) {
        fileBrowserPanel.getButton(PFileBrowserView.CONFIRM_BUTTON).setText(confirmButtonText);
        fileBrowserPanel.getButton(PFileBrowserView.CANCEL_BUTTON).setText(cancelButtonText);
    }

    public void setCurrentDir(File dir) {
        if (!dir.isDirectory()) {
            return;
        }
        modelFactory.getBrowserListModel().open(dir);
    }

    public void setMultipleFiles(boolean flag) {
        int selectionModel = flag ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION : ListSelectionModel.SINGLE_SELECTION;
        fileBrowserPanel.getJList(PFileBrowserView.BROWSER_LIST).setSelectionMode(selectionModel);
    }

    /**
     * 
     * @param parent
     * @return file list with selected values, if operation was canceled return empty list
     */
    public List<File> showOpenListFileDialog(Frame parent) {
        return showOpenListFileDialog(parent, "Abrir");
    }

    public List<File> showOpenListFileDialog(Frame parent, String titleWindow) {
        setMultipleFiles(true);

        canceled = false;
        fileBrowserPanel.getJList(PFileBrowserView.BROWSER_LIST).clearSelection();
        fileBrowserDialog = new JDialog(parent, titleWindow, true);

        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        fileBrowserDialog.setBounds((screenSize.width - width) / 2, (screenSize.height - height) / 2, width, height);
        fileBrowserDialog.add(fileBrowserPanel.getMasterComponent());

        fileBrowserDialog.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                canceled = true;
            }
        });
        fileBrowserDialog.setVisible(true);

        return canceled ? Collections.EMPTY_LIST : getSelectedFiles();
    }

    /**
     * 
     * @param parent
     * @return file selected or null if canceled
     */
    public File showOpenFileDialog(Frame parent) {
        return showOpenFileDialog(parent, "Abrir");
    }
    
    public File showOpenFileDialog(Frame parent, String titleWindow) {
        setMultipleFiles(false);

        List<File> listFile = showOpenListFileDialog(parent, titleWindow);
        return listFile == null ? null : (listFile.isEmpty() ? null : listFile.get(0));
    }

    private List<File> getSelectedFiles() {
        JList browserList = (JList) fileBrowserPanel.getComponent(PFileBrowserView.BROWSER_LIST);

        List<File> list = new ArrayList<File>();
        for (Object o : browserList.getSelectedValues()) {
            list.add(((PFileView) o).getFile());
        }

        return list;
    }

    public void showSaveDialog() {
    }

    public void addFileFilter(FileFilter fileFilter) {
        fileFilters.add(fileFilter);
        Component component = (Component) fileBrowserPanel.getComponent(PFileBrowserView.BROWSER_LIST);
        component.repaint();
    }

    public void removeFileFilter(FileFilter fileFilter) {
        fileFilters.remove(fileFilter);
        Component component = (Component) fileBrowserPanel.getComponent(PFileBrowserView.BROWSER_LIST);
        component.repaint();
    }

    private class ConfirmActionListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            boolean invalid = false;
            for (FileFilter filter : fileFilters) {
                for (File file : getSelectedFiles()) {
                    if (!filter.accept(file)) {
                        invalid = true;
                    }
                }
            }

            if (getSelectedFiles().isEmpty()) {
                invalid = true;
            }

            if (!invalid) {
                fileBrowserDialog.setVisible(false);
            }
        }
    }

    private class CancelActionListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            canceled = true;
            fileBrowserDialog.setVisible(false);
        }
    }

    private class FileFilterCellRenderer extends DefaultListCellRenderer {

        private ListCellRenderer original;

        public FileFilterCellRenderer(ListCellRenderer original) {
            this.original = original;
        }

        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            JLabel label = (JLabel) original.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            PFileView fileView = (PFileView) value;

            label.setForeground(isSelected ? Color.WHITE : Color.BLACK);
            for (FileFilter filter : fileFilters) {
                if (!filter.accept(fileView.getFile())) {
                    label.setForeground(Color.GRAY);
                }
            }

            return label;
        }
    }
}
